package summer.codegenerator.service.base;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import javax.persistence.Id;

import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import summer.codegenerator.persistence.hibernate.base.BaseDao;
import summer.codegenerator.persistence.hibernate.base.tool.Condition;
import summer.codegenerator.common.util.ClazzUtil;


/**
 * 
 *
 * @author jiangz
 * @version 1.0 Created on 2019年7月25日 下午2:12:15
 */
@Service
public class CommonServiceImpl implements CommonService {
	
	@Override
	public void cudEntityListData(BaseDao listItemDao, Collection cSaving, Collection cSaved) {
		Set<Long> survivorIds = new HashSet<Long>();
		if(CollectionUtils.isEmpty(cSaving)) {
			for(Object itemSaving : cSaving) {
				Long survivorId = this.getEntityId(itemSaving);
				if(survivorId != null) {
					survivorIds.add(survivorId);
					listItemDao.update(itemSaving);
				} else {
					listItemDao.save(itemSaving);
				}
			}
		}
		if(CollectionUtils.isEmpty(cSaved)) {
			for(Object itemSaved : cSaved) {
				Long itemIdSavedId = this.getEntityId(itemSaved);
				if(!survivorIds.contains(itemIdSavedId)) {
					listItemDao.delete(itemIdSavedId);
				}
			}
		}
		listItemDao.flushThenClear();
	}
	
	
	@Override
	public void cudEntityListData(BaseDao listItemDao, Object entity) {
		// 待保存列表项类对象
		Class<?> subItemClazz = listItemDao.getPersistClass();
		// 主体数据类对象
		Class<?> entityClazz = entity.getClass();
		// 主体数据类对象的所有方法
		Method[] entityMethods = entityClazz.getDeclaredMethods();
		// 遍历主体数据类的所有方法
		for(Method entityMethod : entityMethods) {
			// 方法名称
			String entityMethodName = entityMethod.getName();
			// 返回值类型
			Class entityMethodReturnType = entityMethod.getReturnType();
			// 返回值为Collection且以"get"开头的方法
			if(entityMethodName.startsWith("get") && 
					Collection.class.isAssignableFrom(entityMethodReturnType)) {
				// 获取返回值类对象泛型参数
				Type cItemClazz = ClazzUtil.getMethodReturnFirstParameterizedClass(entityMethod);
				if(Objects.equals(subItemClazz, cItemClazz)) {
					try {
						// 待保存的列表数据
						Collection cSaving = (Collection<?>) entityMethod.invoke(entity);
						// 列表项类对象的数据类型为主体类的字段名
						String entityFieldName = this.getFieldName(subItemClazz, entityClazz);
						Set<Long> survivorIds = new HashSet<Long>();
						if(!CollectionUtils.isEmpty(cSaving)) {
							for(Object itemSaving : cSaving) {
								this.setEntityField(itemSaving, entity);
								Long survivorId = this.getEntityId(itemSaving);
								if(survivorId != null) {
									listItemDao.update(itemSaving);
								} else {
									listItemDao.save(itemSaving);
								}
								survivorId = this.getEntityId(itemSaving);
								survivorIds.add(survivorId);
							}
							listItemDao.flushThenClear();
						}
						// 已保存的列表数据
						Collection cSaved = listItemDao.list(
								new Condition(entityFieldName, "=", entity, entityFieldName + System.currentTimeMillis()), null);
						if(!CollectionUtils.isEmpty(cSaved)) {
							for(Object itemSaved : cSaved) {
								Long itemIdSavedId = this.getEntityId(itemSaved);
								if(!survivorIds.contains(itemIdSavedId)) {
									listItemDao.delete(itemIdSavedId);
								}
							}
						}
						listItemDao.flushThenClear();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}
					break;
				}
			}
		}
	}
	
	private String getFieldName(Class<?> clazz, Class<?> fieldClazz) {
		Field[] fields = clazz.getDeclaredFields();
		for(Field field : fields) {
			if(Objects.equals(field.getType(), fieldClazz)) {
				return field.getName();
			}
		}
		return null;
	}
	
	private void setEntityField(Object item, Object entity) {
		Method[] itemMethods = item.getClass().getDeclaredMethods();
		for(Method itemMethod : itemMethods) {
			Class<?>[] parameterTypes = itemMethod.getParameterTypes();
			if(parameterTypes != null && parameterTypes.length == 1 &&
					Objects.equals(entity.getClass(), parameterTypes[0])) {
				try {
					itemMethod.invoke(item, entity);
					break;
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 获取实体标识
	 *
	 * 
	 * @param entity	实体
	 * @return
	 * @author: jiangz
	 * @date: Created on 2019年7月24日 上午11:19:58
	 */
	private Long getEntityId(Object entity) {
		Method[] methods = entity.getClass().getDeclaredMethods();
		Method idGetMethod = null;
		for (Method method : methods) {
			Id clazz = method.getAnnotation(Id.class);
			if (clazz != null) {
				idGetMethod = method;
			}
		}
		Long id = null;
		try {
			id = (Long) idGetMethod.invoke(entity);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return id;
	}
}
